#region

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using Mvc.Mailer;
using log4net;
using xConnected.Common.Category;
using xConnected.Common.Country;
using xConnected.Core.Model;
using xConnected.Core.Model.ViewModel;
using xConnected.Core.Model.ViewModel.xConnected.Core.Model.ViewModel;
using xConnected.Mailers;
using xConnected.Service;

#endregion

namespace xConnected.Controllers
{
    public class CompanyProfileController : BaseController<CompanyProfile>
    {
        private readonly CompanyProfileService _companyProfileService;
        private readonly CountryService _countryService;
        private readonly IndustryService _industryService;
        private readonly PositionService _Positionservice;
        private readonly UserService _userService;

        public CompanyProfileController(CompanyProfileService companyProfileService, PositionService Positionservice,
                                        UserService userService, CountryService countryService,
                                        IndustryService industryService)
        {
            _companyProfileService = companyProfileService;
            _Positionservice = Positionservice;
            _userService = userService;
            _countryService = countryService;
            _industryService = industryService;
        }


        public JsonResult ListAdvancedSearchAll(AdvancedSearchModelCompany companyModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (companyModel.UserId == 1)
                {
                    companyModel.UserId = _userService.GetUserByUsername(User.Identity.Name).Id;
                }
                var page = _companyProfileService.AdvancedPagedSearchedAll(companyModel);
                var companies = page.Entities.ToList().Select(c => new
                                                                       {
                                                                           c.Id,
                                                                           c.Created,
                                                                           c.Updated,
                                                                           c.Title,
                                                                           c.Description,
                                                                           c.Location,
                                                                           c.TagLine,
                                                                           c.Website,
                                                                           c.IsDefault,
                                                                           c.Photo,
                                                                           Photo150X150 =
                                                                       c.Photo.Replace("/250X250_", "/150X150_"),
                                                                           Photo80X80 =
                                                                       c.Photo.Replace("/250X250_", "/80X80_"),
                                                                           Photo50X50 =
                                                                           c.Photo.Replace("/250X250_", "/50X50_"),
                                                                           c.Email,
                                                                           c.PhoneNumber,
                                                                           CountryFlag =
                                                                       "../../Content/img/Flags/" +
                                                                       c.Country.ShortName.ToLower() + ".png",
                                                                           Categories = c.Categories.Select(ca => new
                                                                                                                      {
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Id,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Created,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Updated,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Description
                                                                                                                          //    Description
                                                                                                                          //=
                                                                                                                          //CategoryRes
                                                                                                                          //.
                                                                                                                          //ResourceManager
                                                                                                                          //.
                                                                                                                          //GetString
                                                                                                                          //(c
                                                                                                                          //     .
                                                                                                                          //     Key,
                                                                                                                          // Thread
                                                                                                                          //     .
                                                                                                                          //     CurrentThread
                                                                                                                          //     .
                                                                                                                          //     CurrentCulture),
                                                                                                                          //    c
                                                                                                                          //.
                                                                                                                          //Key
                                                                                                                      }),
                                                                           Technologies =
                                                                       c.Technologies.Select(t => new
                                                                                                      {
                                                                                                          t
                                                                                                      .
                                                                                                      Id,
                                                                                                          t
                                                                                                      .
                                                                                                      Created,
                                                                                                          t
                                                                                                      .
                                                                                                      Updated,
                                                                                                          t
                                                                                                      .
                                                                                                      Name
                                                                                                      }),
                                                                           Positions = c.Positions.Select(p => new
                                                                                                                 {
                                                                                                                     p.
                                                                                                                 Id,
                                                                                                                     p.
                                                                                                                 Created,
                                                                                                                     p.
                                                                                                                 Updated,
                                                                                                                     p.
                                                                                                                 Title,
                                                                                                                     p.
                                                                                                                 Description,
                                                                                                                     p.
                                                                                                                 StartDate,
                                                                                                                     p.
                                                                                                                 Duration,
                                                                                                                     p.
                                                                                                                 Location,
                                                                                                                     ContractType
                                                                                                                 = p.
                                                                                                                 JobType,
                                                                                                                     Categories
                                                                                                                 =
                                                                                                                 p.
                                                                                                                 Categories
                                                                                                                 .Select
                                                                                                                 (
                                                                                                                     k
                                                                                                                     =>
                                                                                                                     new
                                                                                                                         {
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Id,
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Created,
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Updated,
                                                                                                                             Description
                                                                                                                         =
                                                                                                                         CategoryRes
                                                                                                                         .
                                                                                                                         ResourceManager
                                                                                                                         .
                                                                                                                         GetString
                                                                                                                         (k
                                                                                                                              .
                                                                                                                              Key,
                                                                                                                          Thread
                                                                                                                              .
                                                                                                                              CurrentThread
                                                                                                                              .
                                                                                                                              CurrentCulture),
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Key
                                                                                                                         }),
                                                                                                                     Technologies
                                                                                                                 =
                                                                                                                 p.
                                                                                                                 Technologies
                                                                                                                 .Select
                                                                                                                 (
                                                                                                                     t
                                                                                                                     =>
                                                                                                                     new
                                                                                                                         {
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Id,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Created,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Updated,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Name
                                                                                                                         })
                                                                                                                 }),
                                                                           Country = new
                                                                                         {
                                                                                             c.Country.Id,
                                                                                             c.Country.Created,
                                                                                             c.Country.Updated,
                                                                                             Description =
                                                                       CountryRes.ResourceManager.GetString(
                                                                           c.Country.Key,
                                                                           Thread.CurrentThread.CurrentCulture),
                                                                                             c.Country.ShortName
                                                                                         },
                                                                           c.CountryId,
                                                                           Industry = new
                                                                                          {
                                                                                              c.Industry.Id,
                                                                                              c.Industry.Created,
                                                                                              c.Industry.Updated,
                                                                                              c.Industry.Description
                                                                                          },
                                                                           c.IndustryId,
                                                                       });


                return Json(new {page.Count, page.PagesCount, Entities = companies},
                            JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult ListAdvancedSearchSome(AdvancedSearchModelCompany companyModel)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                if (companyModel.UserId == 1)
                {
                    companyModel.UserId = _userService.GetUserByUsername(User.Identity.Name).Id;
                }
                var page = _companyProfileService.AdvancedPagedSearchedSome(companyModel);
                var companies = page.Entities.ToList().Select(c => new
                                                                       {
                                                                           c.Id,
                                                                           c.Created,
                                                                           c.Updated,
                                                                           c.Title,
                                                                           c.Description,
                                                                           c.Location,
                                                                           c.TagLine,
                                                                           c.Website,
                                                                           c.IsDefault,
                                                                           Logo = c.Photo,
                                                                           Logo150X150 =
                                                                       c.Photo.Replace("/250X250_", "/150X150_"),
                                                                           Logo80X80 =
                                                                       c.Photo.Replace("/250X250_", "/80X80_"),
                                                                           c.Email,
                                                                           c.PhoneNumber,
                                                                           CountryFlag =
                                                                       "../../Content/img/Flags/" +
                                                                       c.Country.ShortName.ToLower() + ".png",
                                                                           Categories = c.Categories.Select(ca => new
                                                                                                                      {
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Id,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Created,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Updated,
                                                                                                                          ca
                                                                                                                      .
                                                                                                                      Description
                                                                                                                          //    Description
                                                                                                                          //=
                                                                                                                          //CategoryRes
                                                                                                                          //.
                                                                                                                          //ResourceManager
                                                                                                                          //.
                                                                                                                          //GetString
                                                                                                                          //(c
                                                                                                                          //     .
                                                                                                                          //     Key,
                                                                                                                          // Thread
                                                                                                                          //     .
                                                                                                                          //     CurrentThread
                                                                                                                          //     .
                                                                                                                          //     CurrentCulture),
                                                                                                                          //    c
                                                                                                                          //.
                                                                                                                          //Key
                                                                                                                      }),
                                                                           Technologies =
                                                                       c.Technologies.Select(t => new
                                                                                                      {
                                                                                                          t
                                                                                                      .
                                                                                                      Id,
                                                                                                          t
                                                                                                      .
                                                                                                      Created,
                                                                                                          t
                                                                                                      .
                                                                                                      Updated,
                                                                                                          t
                                                                                                      .
                                                                                                      Name
                                                                                                      }),
                                                                           Positions = c.Positions.Select(p => new
                                                                                                                 {
                                                                                                                     p.
                                                                                                                 Id,
                                                                                                                     p.
                                                                                                                 Created,
                                                                                                                     p.
                                                                                                                 Updated,
                                                                                                                     p.
                                                                                                                 Title,
                                                                                                                     p.
                                                                                                                 Description,
                                                                                                                     p.
                                                                                                                 StartDate,
                                                                                                                     p.
                                                                                                                 Duration,
                                                                                                                     p.
                                                                                                                 Location,
                                                                                                                     ContractType
                                                                                                                 = p.
                                                                                                                 JobType,
                                                                                                                     Categories
                                                                                                                 =
                                                                                                                 p.
                                                                                                                 Categories
                                                                                                                 .Select
                                                                                                                 (
                                                                                                                     k
                                                                                                                     =>
                                                                                                                     new
                                                                                                                         {
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Id,
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Created,
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Updated,
                                                                                                                             Description
                                                                                                                         =
                                                                                                                         CategoryRes
                                                                                                                         .
                                                                                                                         ResourceManager
                                                                                                                         .
                                                                                                                         GetString
                                                                                                                         (k
                                                                                                                              .
                                                                                                                              Key,
                                                                                                                          Thread
                                                                                                                              .
                                                                                                                              CurrentThread
                                                                                                                              .
                                                                                                                              CurrentCulture),
                                                                                                                             k
                                                                                                                         .
                                                                                                                         Key
                                                                                                                         }),
                                                                                                                     Technologies
                                                                                                                 =
                                                                                                                 p.
                                                                                                                 Technologies
                                                                                                                 .Select
                                                                                                                 (
                                                                                                                     t
                                                                                                                     =>
                                                                                                                     new
                                                                                                                         {
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Id,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Created,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Updated,
                                                                                                                             t
                                                                                                                         .
                                                                                                                         Name
                                                                                                                         })
                                                                                                                 }),
                                                                           Country = new
                                                                                         {
                                                                                             c.Country.Id,
                                                                                             c.Country.Created,
                                                                                             c.Country.Updated,
                                                                                             Description =
                                                                       CountryRes.ResourceManager.GetString(
                                                                           c.Country.Key,
                                                                           Thread.CurrentThread.CurrentCulture),
                                                                                             c.Country.ShortName
                                                                                         },
                                                                           c.CountryId,
                                                                           Industry = new
                                                                                          {
                                                                                              c.Industry.Id,
                                                                                              c.Industry.Created,
                                                                                              c.Industry.Updated,
                                                                                              c.Industry.Description
                                                                                          },
                                                                           c.IndustryId,
                                                                       });

                return Json(new {page.Count, page.PagesCount, Entities = companies},
                            JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public ActionResult ContactCompany(int id, ContactModel model)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var mailer = new UserMailer(_userService);
                var msg = mailer.Contact(id, model);
                msg.Send();
                return Content("Ok");
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Content("Error");
            }
        }

        [HttpPost]
        public JsonResult Save(CompanyProfile profile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                profile.User = user;

                //set profile as default if it's first user's profile
                if (user.ExpertProfiles.Count == 0 && user.CompanyProfiles.Count == 0)
                {
                    profile.IsDefault = true;
                }

                var selectedPositions = new List<Position>(profile.Positions);
                profile.Positions.Clear();


                // first save the parent entity in order to autogenerate his Id
                _companyProfileService.SaveOrUpdate(profile);

                // then set this Id to all his child relationships foreign key properties
                profile.Positions = new List<Position>(selectedPositions);

                foreach (var project in profile.Positions)
                {
                    project.CompanyProfileId = profile.Id;
                }

                //create directories for the new profile
                var di1 =
                    new DirectoryInfo(
                        Server.MapPath("~/Content/Uploads/" +
                                       Path.Combine(user.Username, "CompanyProfiles", profile.Id.ToString(), "Photo")));
                di1.Create();

                var di2 =
                    new DirectoryInfo(
                        Server.MapPath("~/Content/Uploads/" +
                                       Path.Combine(user.Username, "CompanyProfiles", profile.Id.ToString(), "Cv")));
                di2.Create();

                //Save Photo
                var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                var fileNameLogo = profile.Photo.Substring(profile.Photo.IndexOf("/250X250_") + 9);
                var directoryLogo = Server.MapPath("~/Content/Uploads/" + Path.Combine(username, "CompanyProfiles", profile.Id.ToString(), "Photo"));

                var dirLogo = new DirectoryInfo(directoryLogo);
                if (!dirLogo.Exists)
                    dirLogo.Create();

                foreach (var fi in dirLogo.GetFiles())
                {
                    if (!fi.FullName.Contains("\\250X250_" + fileNameLogo) &&
                        !fi.FullName.Contains("\\150X150_" + fileNameLogo) &&
                        !fi.FullName.Contains("\\80X80_" + fileNameLogo))
                    {
                        fi.Delete();
                    }
                }
                _companyProfileService.SaveOrUpdate(profile);

                return Json(profile.Id, JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult Update(CompanyProfile profile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                // load the old entity from the DB
                var oldProfile = _companyProfileService.GetById(profile.Id);
                var user = _userService.GetUserByUsername(User.Identity.Name);

                //if the profile belongs to current user save changes
                if (oldProfile.UserId == user.Id)
                {
                    profile.User = user;

                    // manually set new property values
                    oldProfile.Title = profile.Title;
                    oldProfile.Description = profile.Description;
                    oldProfile.Website = profile.Website;
                    oldProfile.TagLine = profile.TagLine;
                    oldProfile.Location = profile.Location;
                    oldProfile.Email = profile.Email;
                    oldProfile.PhoneNumber = profile.PhoneNumber;
                    oldProfile.CountryId = profile.CountryId;
                    oldProfile.IndustryId = profile.IndustryId;

                    //Save Photo
                    var username = _userService.GetUserByUsername(User.Identity.Name).Username;
                    var fileNameLogo = profile.Photo.Substring(profile.Photo.IndexOf("/250X250_") + 9);
                    var directoryLogo = Server.MapPath("~/Content/Uploads/" + Path.Combine(username, "CompanyProfiles", profile.Id.ToString(), "Photo"));

                    var dirLogo = new DirectoryInfo(directoryLogo);
                    if (!dirLogo.Exists)
                        dirLogo.Create();

                    foreach (var fi in dirLogo.GetFiles())
                    {
                        if (!fi.FullName.Contains("\\250X250_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\150X150_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\80X80_" + fileNameLogo) &&
                            !fi.FullName.Contains("\\50X50_" + fileNameLogo))
                        {
                            fi.Delete();
                        }
                    }
                    oldProfile.Photo = profile.Photo;

                    var PositionsIds = profile.Positions.Select(s => s.Id);
                    //from all the Position we find those that exist in the new profile, by ID
                    var Positions = _Positionservice.GetAll().Where(c => PositionsIds.Contains(c.Id)).ToList();

                    // clean the old relationships and set the new ones
                    oldProfile.Positions.Clear();

                    // Positions require to set their foreign key because they are "one to many" relationship
                    // for the "many to many" it is enough to add it to the list
                    //add the Positions of the new profile to the old profile
                    Positions.ForEach(p => oldProfile.Positions.Add(p));

                    _companyProfileService.SaveOrUpdate(oldProfile);

                    return Json(profile.Id, JsonRequestBehavior.AllowGet);
                }
                //else if the profile doesn't belong to current user return "error" which means to render "you are not allowed...." message on client side
                return Json("ERROR", JsonRequestBehavior.AllowGet);
            }

            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult DeleteCompanyProfile(int id)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var companyProfile = _companyProfileService.GetById(id);

                var PositionsToBeDeleted = new List<Position>(companyProfile.Positions);

                foreach (var project in PositionsToBeDeleted)
                {
                    //foreach (var category in Position.Categories)
                    //{
                    //    _projectCategoryService.Delete(Position);
                    //}
                    //foreach (var tec in Position.Technologies)
                    //{
                    //    _projectTechnologyService.Delete(tec);
                    //}


                    _Positionservice.Delete(project);
                }

                //companyProfile.Positions.Clear();
                //_companyProfileService.SaveOrUpdate(companyProfile);

                _companyProfileService.Delete(companyProfile);
                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public ActionResult CheckSignedIn(int companyProfileId)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var user = _userService.GetUserByUsername(User.Identity.Name);
                var profileIds = user.CompanyProfiles.Select(p => p.Id);

                //if user is signed in and the current profile belongs to that user
                if (user != null && profileIds.Contains(companyProfileId))
                {
                    return Json(true, JsonRequestBehavior.AllowGet);
                }
                return Json(false, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Content("ERROR");
            }
        }

        public JsonResult GetCompaniesAutocomplete(string searchTerm, int maxRows)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var companies = _companyProfileService.GetAll().ToList().OrderBy(c => c.Title).Select(c => new
                                                                                                               {
                                                                                                                   c.
                                                                                                               Title,
                                                                                                                   c.Id
                                                                                                               });
                if (searchTerm != "")
                {
                    companies =
                        companies.Where(c => c.Title.ToLower().Contains(searchTerm.ToLower())).Take(maxRows);
                }
                return Json(companies, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        public JsonResult GetKeywordsAutocomplete(string searchTerm = "", int maxRows = 8)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var countries = _countryService.GetAll().Select(l => new
                                                                         {
                                                                             l.Description,
                                                                             l.Id,
                                                                             Type = "co"
                                                                         });
                var industries = _industryService.GetAll().Select(l => new
                                                                           {
                                                                               l.Description,
                                                                               l.Id,
                                                                               Type = "in"
                                                                           });

                var keywords = countries.Union(industries);
                if (searchTerm != "")
                {
                    keywords =
                        keywords.Where(l => l.Description.ToLower().Contains(searchTerm.ToLower())).Take(maxRows);
                }
                return Json(keywords, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new {Result = "ERROR", ex.Message}, JsonRequestBehavior.AllowGet);
            }
        }

        [HttpPost]
        public JsonResult SetAsDefault(CompanyProfile companyProfile)
        {
            ILog log = LogManager.GetLogger(GetType());
            try
            {
                var profile = _companyProfileService.GetById(companyProfile.Id);
                var user = profile.User;
                //set isdefault=false to all other profiles that belong to current user
                user.ExpertProfiles.ToList().ForEach(e => e.IsDefault = false);
                user.CompanyProfiles.ToList().ForEach(c => c.IsDefault = false);
                foreach (var company in user.CompanyProfiles)
                {
                    foreach (var project in company.Positions)
                    {
                        project.IsDefault = false;
                    }
                }

                profile.IsDefault = true;
                _companyProfileService.SaveOrUpdate(profile);
                return Json("OK", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message + Environment.NewLine + "Stack: " + ex.StackTrace, ex);
                return Json(new { Result = "ERROR", ex.Message }, JsonRequestBehavior.AllowGet);
            }
        }
    }
}